# !/usr/bin/python3
# -*- coding: utf-8 -*-
# @Time    : 2019/8/19 14:15
# @Author  : LiHaowen
# @Email   : lihaowen2017@163.com
from django.urls import reverse_lazy
# django 的消息机制
from django.contrib import messages
from django.http import JsonResponse
from django.core.exceptions import PermissionDenied  # django 的异常处理
from django.contrib.auth.decorators import login_required  # 校验登录装饰器
from django.contrib.auth.mixins import LoginRequiredMixin  # 校验登录继承类
from django.views.decorators.http import require_http_methods  # http请求方法的装饰器
from django.views.generic import CreateView, ListView, UpdateView, DetailView

from web_ask.helpers import ajax_required
from web_ask.qa.models import Question, Answer  # 使用self.vote进行关联所以Vote不用导入，
from web_ask.qa.forms import QuestionForm
from web_ask.notifications.views import notification_handler


class QuestionListView(LoginRequiredMixin, ListView):
    """所有问题页"""
    model = Question
    queryset = Question.objects.select_related('user')
    paginate_by = 10
    context_object_name = "questions"
    template_name = "qa/question_list.html"

    def get_context_data(self, *, object_list=None, **kwargs):
        # 重载上下文父类的方法
        context = super(QuestionListView, self).get_context_data()
        context["popular_tags"] = Question.objects.get_counted_tags()  # 页面的标签功能
        context["active"] = "all"
        return context


class AnsweredQuestionListView(QuestionListView):
    """已有采纳答案的问题"""

    def get_queryset(self):
        return Question.objects.get_answered()

    def get_context_data(self, *, object_list=None, **kwargs):
        # 重载上下文父类的方法
        context = super(AnsweredQuestionListView, self).get_context_data()
        context["active"] = "answered"
        return context


class UnansweredQuestionListView(QuestionListView):
    """未有采纳答案的问题"""

    def get_queryset(self):
        return Question.objects.get_unanswered()

    def get_context_data(self, *, object_list=None, **kwargs):
        # 重载上下文父类的方法
        context = super(UnansweredQuestionListView, self).get_context_data()
        context["active"] = "unanswered"
        return context


class CreateQuestionView(LoginRequiredMixin, CreateView):
    """用户提问"""
    # model = Question
    form_class = QuestionForm
    template_name = "qa/question_form.html"
    message = "问题已提交"

    def form_valid(self, form):
        form.instance.user = self.request.user
        return super(CreateQuestionView, self).form_valid(form)

    def get_success_url(self):
        messages.success(self.request, self.message)
        return reverse_lazy("qa:unanswered_q")


class QuestionDetailView(LoginRequiredMixin, DetailView):
    """问题详情页"""
    model = Question
    context_object_name = "question"
    template_name = "qa/question_detail.html"

    def get_queryset(self):
        return Question.objects.select_related('user').filter(pk=self.kwargs['pk'])


class CreateAnswerView(LoginRequiredMixin, CreateView):
    """回答问题"""
    model = Answer
    fields = ["content", ]  # 表单中校验的字段
    message = "您的回答已提交"
    template_name = "qa/answer_form.html"

    def form_valid(self, form):
        form.instance.user = self.request.user
        # 添加校验字段问题id
        form.instance.question_id = self.kwargs["question_id"]
        return super(CreateAnswerView, self).form_valid(form)

    def get_success_url(self):
        question_id = self.kwargs["question_id"]
        question = Question.objects.get(pk=question_id)
        notification_handler(self.request.user, question.user, "A", question)
        messages.success(self.request, self.message)
        return reverse_lazy("qa:question_detail", kwargs={"pk": self.kwargs["question_id"]})


@login_required
@ajax_required
@require_http_methods(["POST"])
def question_vote(request):
    """给问题投票，Ajax POST请求"""
    question_id = request.POST["question"]
    value = True if request.POST["value"] == "U" else False  # 前端传递'U'表示赞 'D'表示踩
    question = Question.objects.get(pk=question_id)
    users = question.votes.values_list("user", flat=True)  # 当前问题的所有投票用户

    if request.user.pk in users and (question.votes.get(user=request.user).value == value):
        # 当前用户为赞或踩的情况，取消赞，踩(接收到的值与表中值一样且操作用户在当前问题的所有投票用户中)
        question.votes.get(user=request.user).delete()
    else:
        # 当前操作用户不在当前问题的所有投票用户中，或者原本状态与传递状态不一致，创建状态或更新状态。
        question.votes.update_or_create(user=request.user, defaults={"value": value})
    """
    # 1. 用户首次操作点赞或者踩
    if request.user.pk not in users:
        question.votes.create(user=request.user, value=value)
    # 2. 用户已经赞过，要取消赞/踩一下
    elif question.votes.get(user=request.user).value:
        # 取消赞(传递的True)
        if value:
            question.votes.get(user=request.user).delete()
        # 赞变踩
        else:
            question.votes.update(user=request.user, value=value)
    # 3. 用户已经踩过，取消踩/赞一下
    else:
        # 取消踩(传递的False)
        if not value:
            question.votes.get(user=request.user).delete()
        # 踩变赞
        else:
            question.votes.update(user=request.user, value=value)
    """
    return JsonResponse({"vote": question.total_votes()})


@login_required
@ajax_required
@require_http_methods(["POST"])
def answer_vote(request):
    """给回答投票，Ajax POST请求"""
    answer_id = request.POST["answer"]
    value = True if request.POST["value"] == "U" else False  # 前端传递'U'表示赞 'D'表示踩
    answer = Answer.objects.get(pk=answer_id)
    users = answer.votes.values_list("user", flat=True)  # 当前问题的所有投票用户

    if request.user.pk in users and (answer.votes.get(user=request.user).value == value):
        # 当前用户为赞或踩的情况，取消赞，踩(接收到的值与表中值一样且操作用户在当前问题的所有投票用户中)
        answer.votes.get(user=request.user).delete()
    else:
        # 当前操作用户不在当前问题的所有投票用户中，或者原本状态与传递状态不一致，创建状态或更新状态。
        answer.votes.update_or_create(user=request.user, defaults={"value": value})

    return JsonResponse({"vote": answer.total_votes()})


@login_required
@ajax_required
@require_http_methods(["POST"])
def accept_answer(request):
    """
    接收回答，AJAX POST请求
    已经被接受的回答用户不能取消
    """
    answer_id = request.POST["answer"]
    answer = Answer.objects.get(pk=answer_id)
    # 如果当前登录用户不是提问者，抛出权限拒绝错误
    # 直接使用user有可能发生类型不一样的错误，然而使用username则不会发生该问题
    if answer.question.user.username != request.user.username:
        raise PermissionDenied  # 权限错误
    answer.accept_answer()
    # 通知回答者
    notification_handler(request.user, answer.user, 'W', answer)
    return JsonResponse({"status": "true"})

